home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dskut / aspisrc.zip / WILDMAT.C < prev   
C/C++ Source or Header  |  1992-01-26  |  4KB  |  152 lines

  1. /* Wildcard matching routines.
  2.    Copyright (C) 1988 Free Software Foundation
  3.  
  4. This file is part of GNU Tar.
  5.  
  6. GNU Tar is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GNU Tar is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Tar; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * @(#)wildmat.c 1.3 87/11/06
  22.  *
  23. From: rs@mirror.TMC.COM (Rich Salz)
  24. Newsgroups: net.sources
  25. Subject: Small shell-style pattern matcher
  26. Message-ID: <596@mirror.TMC.COM>
  27. Date: 27 Nov 86 00:06:40 GMT
  28.  
  29. There have been several regular-expression subroutines and one or two
  30. filename-globbing routines in mod.sources.  They handle lots of
  31. complicated patterns.  This small piece of code handles the *?[]\
  32. wildcard characters the way the standard Unix(tm) shells do, with the
  33. addition that "[^.....]" is an inverse character class -- it matches
  34. any character not in the range ".....".  Read the comments for more
  35. info.
  36.  
  37. For my application, I had first ripped off a copy of the "glob" routine
  38. from within the find source, but that code is bad news:  it recurses
  39. on every character in the pattern.  I'm putting this replacement in the
  40. public domain.  It's small, tight, and iterative.  Compile with -DTEST
  41. to get a test driver.  After you're convinced it works, install in
  42. whatever way is appropriate for you.
  43.  
  44. I would like to hear of bugs, but am not interested in additions; if I
  45. were, I'd use the code I mentioned above.
  46. */
  47. /*
  48. **  Do shell-style pattern matching for ?, \, [], and * characters.
  49. **  Might not be robust in face of malformed patterns; e.g., "foo[a-"
  50. **  could cause a segmentation violation.
  51. **
  52. **  Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
  53. */
  54.  
  55. /*
  56.  * Modified 6Nov87 by John Gilmore (hoptoad!gnu) to return a "match"
  57.  * if the pattern is immediately followed by a "/", as well as \0.
  58.  * This matches what "tar" does for matching whole subdirectories.
  59.  *
  60.  * The "*" code could be sped up by only recursing one level instead
  61.  * of two for each trial pattern, perhaps, and not recursing at all
  62.  * if a literal match of the next 2 chars would fail.
  63.  */
  64. #define TRUE        1
  65. #define FALSE        0
  66.  
  67.  
  68. static int
  69. Star(s, p)
  70.     register char    *s;
  71.     register char    *p;
  72. {
  73.     while (wildmat(s, p) == FALSE)
  74.     if (*++s == '\0')
  75.         return(FALSE);
  76.     return(TRUE);
  77. }
  78.  
  79.  
  80. int
  81. wildmat(s, p)
  82.     register char    *s;
  83.     register char    *p;
  84. {
  85.     register int      last;
  86.     register int      matched;
  87.     register int      reverse;
  88.  
  89.     for ( ; *p; s++, p++)
  90.     switch (*p) {
  91.         case '\\':
  92.         /* Literal match with following character; fall through. */
  93.         p++;
  94.         default:
  95.         if (*s != *p)
  96.             return(FALSE);
  97.         continue;
  98.         case '?':
  99.         /* Match anything. */
  100.         if (*s == '\0')
  101.             return(FALSE);
  102.         continue;
  103.         case '*':
  104.         /* Trailing star matches everything. */
  105.         return(*++p ? Star(s, p) : TRUE);
  106.         case '[':
  107.         /* [^....] means inverse character class. */
  108.         if (reverse = p[1] == '^')
  109.             p++;
  110.         for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p)
  111.             /* This next line requires a good C compiler. */
  112.             if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
  113.             matched = TRUE;
  114.         if (matched == reverse)
  115.             return(FALSE);
  116.         continue;
  117.     }
  118.  
  119.     /* For "tar" use, matches that end at a slash also work. --hoptoad!gnu */
  120.     return(*s == '\0' || *s == '/');
  121. }
  122.  
  123.  
  124. #ifdef    TEST
  125. #include <stdio.h>
  126.  
  127. extern char    *gets();
  128.  
  129.  
  130. main()
  131. {
  132.     char     pattern[80];
  133.     char     text[80];
  134.  
  135.     while (TRUE) {
  136.     printf("Enter pattern:  ");
  137.     if (gets(pattern) == NULL)
  138.         break;
  139.     while (TRUE) {
  140.         printf("Enter text:  ");
  141.         if (gets(text) == NULL)
  142.         exit(0);
  143.         if (text[0] == '\0')
  144.         /* Blank line; go back and get a new pattern. */
  145.         break;
  146.         printf("      %d\n", wildmat(text, pattern));
  147.     }
  148.     }
  149.     exit(0);
  150. }
  151. #endif    /* TEST */
  152.